import re
from django.contrib.auth import login
import logging
from django.conf import settings
from django import http
from django.shortcuts import render, redirect
from django.views import View
from QQLoginTool.QQtool import OAuthQQ
from django_redis import get_redis_connection

from carts.utils import merge_cart_cookie_to_redis
from . import sinaweibopy3
from meiduo_mall.utils.response_code import RETCODE
from users.models import User
from .models import oAuthQQUser, OAuthJacksonUser
from .utils import generate_openid_signature, check_openid_signature


logger = logging.getLogger('django')

class OAuthURLView(View):
    """获取登陆页面"""
    def get(self, request):
        next = request.GET.get('next', '/')   #要是没有返回的网页就直接跳到首页
        # QQ_CLIENT_ID = '101518219'
        # QQ_CLIENT_SECRET = '418d84ebdc7241efb79536886ae95224'
        # QQ_REDIRECT_URI = 'http://www.meiduo.site:8000/oauth_callback'
       #  OAuthQQ模块封装了需要的撒谎那个参数
        oauch = OAuthQQ(
            client_id=settings.QQ_CLIENT_ID,
            client_secret=settings.QQ_CLIENT_SECRET,
            redirect_uri=settings.QQ_REDIRECT_URI,
            state=next,
        )
        # login_url是固定的也是封装好的，直接用就好了
        login_url = oauch.get_qq_url()

        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'login_url': login_url})

class OAuthUserView(View):
    """qq页面回调函数"""
    def get(self, request):
        # 提取code
        code = request.GET.get('code')
        if code is None:
            return http.HttpResponseForbidden('缺少code')
        # 创建响应对象
        oauth = OAuthQQ(
            client_id=settings.QQ_CLIENT_ID,
            client_secret=settings.QQ_CLIENT_SECRET,
            redirect_uri=settings.QQ_REDIRECT_URI,
            state=next,
        )
        try:
            # 通过code来获取access_token
            access_token = oauth.get_access_token(code)
            # 通过access来获取openid
            openid = oauth.get_open_id(access_token)
        except Exception as e:
            logger.error(e)
            return http.HttpResponseServerError('QQ登陆失败')
        try:
            # 去数据库寻找数据
            oauth_model = oAuthQQUser.objects.get(openid=openid)
        except oAuthQQUser.DoesNotExist:
            # 如果没有绑定就把绑定页面渲染给他

            # openid 是敏感数据需要加密处理
            openid = generate_openid_signature(openid)
            context = {'openid': openid}
            return render(request, 'oauth_callback.html', context)
        else:
            # 已经是用户了直接登陆成功
            # 通过外建获取openid
            user = oauth_model.user
            # 状态保持
            login(request, user)
            # 构建响应体
            response = redirect(request.GET.get('state')or '/')
            response.set_cookie('username', user.username, max_age=settings.SESSION_COOKIE_AGE)
            return response
    def post(self, request):

        # 接收请体的表单数据 POST
        mobile = request.POST.get('mobile')
        password = request.POST.get('password')
        sms_code_client = request.POST.get('sms_code')
        openid = request.POST.get('openid')
        # 校验
        if all([mobile, password, sms_code_client]) is False:
            return http.HttpResponseForbidden('缺少必传参数')
        # 利用手机号查询user表,如果查询到用户,说明是老用户
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseForbidden('手机号码格式不正确')
        # 如果是老用户,再校验一个密码是否能对上
        if not re.match(r'[0-9a-zA-z]{8,20}$', password):
            return http.HttpResponseForbidden('密码格式错误，请输入8-20位的密码')
        # 判断短信验证码是否一致
        redis_conn = get_redis_connection('verify_code')
        sms_code_server = redis_conn.get('sms_code_%s' % mobile)
        if sms_code_server is None:
            return render(request, 'oauth_callback.html', {'sms_code_errmsg': '无效的短信验证码'})
        if sms_code_client != sms_code_server.decode():
            return render(request, 'oauth_callback.html', {'sms_code_errmsg': '输入短信验证码有误'})
        try:
            # 如果使用手机号查询到user,说明是老用户
            user = User.objects.get(mobile=mobile)
            # 是老用户就再校验密码
            if user.check_password(password) is False:
                return render(request, 'oauth_callback.html', {'account_errmsg': '用户名或密码错误'})
        except User.DoesNotExist:
            # 新用户就create_user 方法创建用户
            user = User.objects.create_user(username=mobile, password=password, mobile=mobile)
        # 对openid进行解密
        openid = check_openid_signature(openid)
        if openid is None:
            return http.HttpResponseForbidden('openid无效')
        # 新老用户绑定openid
        oAuthQQUser.objects.create(user=user,openid=openid,)
        # 登录成功后要做的事情
        # 状态保持
        login(request, user)
        # 创建响应
        response = redirect(request.GET.get('state') or '/')
        response.set_cookie('username', user.username, max_age=settings.SESSION_COOKIE_AGE)
        # 返回响应
        merge_cart_cookie_to_redis(request,response)
        return response
    # OAuthQQUser.objects.create(
    #     openid=openid,
    #     user = user
    # )

class OAuthWbURLView(View):
    def get(self, request):
        next = request.GET.get('next', '/')  # 要是没有返回的网页就直接跳到首页
        Weibo_ID = '610102566'
        Weibo_SECRET = '60b98eec217e665fed94375e8570eace'
        Weibo_URl = 'http://www.meiduo.site:8000/sina_callback'
        #  sinaweibopy3模块封装了需要的参数
        client = sinaweibopy3.APIClient(
            app_key=Weibo_ID,
            app_secret=Weibo_SECRET,
            redirect_uri=Weibo_URl
        )
        url = client.get_authorize_url()

        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'login_url': url})

class OAuthWbView(View):
    """weibo页面回调函数"""
    def get(self, request):
        # 提取code
        code = request.GET.get('code')
        if code is None:
            return http.HttpResponseForbidden('缺少code')
        # 创建响应对象
        Weibo_ID = '610102566'
        Weibo_SECRET = '60b98eec217e665fed94375e8570eace'
        Weibo_URl = 'http://www.meiduo.site:8000/sina_callback'
        #  sinaweibopy3模块封装了需要的参数
        sina = sinaweibopy3.APIClient(
            app_key=Weibo_ID,
            app_secret=Weibo_SECRET,
            redirect_uri=Weibo_URl,
        )
        try:
            ret = sina.request_access_token(code)
            access_token = ret.access_token
            uid = ret.uid
        except Exception as e:
            logger.error(e)
            return http.HttpResponseServerError('微博登陆失败')
        try:
            # 去数据库寻找数据
            oauth_model = OAuthJacksonUser.objects.get(uid=uid)
        except OAuthJacksonUser.DoesNotExist:
            # 如果没有绑定就把绑定页面渲染给他

            # uid 是敏感数据需要加密处理
            uid = generate_openid_signature(uid)
            context = {'openid': uid}
            return render(request, 'oauth_callback.html', context)
        else:
            # 已经是用户了直接登陆成功
            # 通过外建获取openid
            user = oauth_model.user
            # 状态保持
            login(request, user)
            # 构建响应体
            response = redirect(request.GET.get('state')or '/')
            response.set_cookie('username', user.username, max_age=settings.SESSION_COOKIE_AGE)
            return response
    def post(self, request):
        # 接收请体的表单数据 POST
        mobile = request.POST.get('mobile')
        password = request.POST.get('password')
        sms_code_client = request.POST.get('sms_code')
        uid = request.POST.get('openid')
        # 校验
        if all([mobile, password, sms_code_client, uid]) is False:
            return http.HttpResponseForbidden('缺少必传参数')
        # 利用手机号查询user表,如果查询到用户,说明是老用户
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseForbidden('手机号码格式不正确')
        # 如果是老用户,再校验一个密码是否能对上
        if not re.match(r'[0-9a-zA-z]{8,20}$', password):
            return http.HttpResponseForbidden('密码格式错误，请输入8-20位的密码')
        # 判断短信验证码是否一致
        redis_conn = get_redis_connection('verify_code')
        sms_code_server = redis_conn.get('sms_code_%s' % mobile)
        if sms_code_server is None:
            return render(request, 'oauth_callback.html', {'sms_code_errmsg': '无效的短信验证码'})
        if sms_code_client != sms_code_server.decode():
            return render(request, 'oauth_callback.html', {'sms_code_errmsg': '输入短信验证码有误'})
        try:
            # 如果使用手机号查询到user,说明是老用户
            user = User.objects.get(mobile=mobile)
            # 是老用户就再校验密码
            if user.check_password(password) is False:
                return render(request, 'oauth_callback.html', {'account_errmsg': '用户名或密码错误'})
        except User.DoesNotExist:
            # 新用户就create_user 方法创建用户
            user = User.objects.create_user(username=mobile, password=password, mobile=mobile)
        # 对openid进行解密
        uid = check_openid_signature(uid)
        if uid is None:
            return http.HttpResponseForbidden('uid无效')
        # 新老用户绑定openid
        OAuthJacksonUser.objects.create(user=user, uid=uid,)
        # 登录成功后要做的事情
        # 状态保持
        login(request, user)
        # 创建响应
        response = redirect(request.GET.get('state') or '/')
        response.set_cookie('username', user.username, max_age=settings.SESSION_COOKIE_AGE)
        # 返回响应
        merge_cart_cookie_to_redis(request,response)
        return response
